﻿using System;
using System.Collections.Generic;
using System.Text;

using PlayerMap = System.Collections.Generic.Dictionary<int, objectinfo.PlayerInfoDigest>;
using ObjectMap = System.Collections.Generic.Dictionary<int, objectinfo.LogicObject>;

/**
*@file       posworld.cs
*@brief      pos world stuff
*
*@author     graywind
*@version    1.0.0.1
*@data       2012/03/06
*/

public class PosWorldInitializer
{
    /// <summary>
    /// override this function later
    /// </summary>
    protected virtual void DoInit()
    {

    }
}

public partial class PosWorld : PosWorldInitializer
{
    #region private variable
    //player objects
    private PlayerMap m_mapPlayer = new PlayerMap();
    //objects of all npc
    private ObjectMap m_mapObject = new ObjectMap();
    //lock object
    private Object    m_lockObj   = new Object();
    #endregion

    #region events
    //define delegate type when player enter the world
    public delegate void PlayerEnter(objectinfo.PlayerInfoDigest digest);
    //define the event when player enter the world
    private event PlayerEnter m_playerEnterEvent;
    /// <summary>
    /// define the event when player enter the world
    /// </summary>
    public PlayerEnter PlayerEnterEvent
    {
        get
        {
            lock (m_playerEnterEvent)
            {
                return m_playerEnterEvent;
            }
        }
        set
        {
            lock (m_playerEnterEvent)
            {
                m_playerEnterEvent = value;
            }
        }
    }

    //define delegate type when player leave the world
    public delegate void PlayerLeave(objectinfo.PlayerInfoDigest digest);
    //define the event when player leave the world
    private event PlayerLeave m_playerLeaveEvent;
    /// <summary>
    /// define the event when player leave the world
    /// </summary>
    public PlayerLeave PlayerLeaveEvent
    {
        get
        {
            lock (m_playerLeaveEvent)
            {
                return m_playerLeaveEvent;
            }
        }
        set
        {
            lock (m_playerLeaveEvent)
            {
                m_playerLeaveEvent = value;
            }
        }
    }

    //define delegate type when object enter the world
    public delegate void ObjectEnter(objectinfo.LogicObject obj);
    //define the event when object enter the world
    private event ObjectEnter m_objectEnterEvent;
    /// <summary>
    /// define the event when object enter the world
    /// </summary>
    public ObjectEnter ObjectEnterEvent
    {
        get
        {
            lock (m_objectEnterEvent)
            {
                return m_objectEnterEvent;
            }
        }
        set
        {
            lock (m_objectEnterEvent)
            {
                m_objectEnterEvent = value;
            }
        }
    }

    //define delegate type when object leave the world
    public delegate void ObjectLeave(objectinfo.LogicObject obj);
    //define the event when object leave the world
    private event ObjectLeave m_objectLeaveEvent;
    /// <summary>
    /// define the event when object leave the world
    /// </summary>
    public ObjectLeave ObjectLeaveEvent
    {
        get
        {
            lock (m_objectLeaveEvent)
            {
                return m_objectLeaveEvent;
            }
        }
        set
        {
            lock (m_objectLeaveEvent)
            {
                m_objectLeaveEvent = value;
            }
        }
    }
    #endregion

    #region property
    //world identifier
    private int m_id;
    /// <summary>
    /// world identifier(read only)
    /// </summary>
    public int WorldId
    {
        get
        {
            return m_id;
        }
        private set
        {
            m_id = value;
        }
    }
    #endregion

    #region private call
    /// <summary>
    /// load configure
    /// </summary>
    /// <param name="world_id"></param>
    /// <param name="config_file"></param>
    void LoadConfig(int world_id, string config_file)
    {

    }
    #endregion

    #region constructor
    /// <summary>
    /// constructor
    /// </summary>
    /// <param name="world_id"></param>
    private PosWorld(int world_id)
    {
        WorldId = world_id;

        DoInit();
    }
    #endregion

    #region static call
    /// <summary>
    /// create a instance
    /// </summary>
    /// <param name="world_id"></param>
    /// <param name="config_file"></param>
    /// <returns></returns>
    public static PosWorld CreateWorld(int world_id, string config_file)
    {
        PosWorld pw = new PosWorld(world_id);
        pw.LoadConfig(world_id, config_file);
        return pw;
    }
    #endregion

    #region external call
    /// <summary>
    /// add a player into this world
    /// </summary>
    /// <param name="playerDigest"></param>
    /// <returns></returns>
    public bool Add(objectinfo.PlayerInfoDigest playerDigest)
    {
        lock (m_lockObj)
        {
            if (!m_mapPlayer.ContainsKey(playerDigest.ObjectInfo.ObjectId))
            {
                m_mapPlayer.Add(playerDigest.ObjectInfo.ObjectId, playerDigest);
                m_mapObject.Add(playerDigest.ObjectInfo.ObjectId, playerDigest.ObjectInfo);

                if (PlayerEnterEvent != null)
                    PlayerEnterEvent(playerDigest);

                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// add a npc or monster into this world
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public bool Add(objectinfo.LogicObject obj)
    {
        lock (m_lockObj)
        {
            if (!m_mapObject.ContainsKey(obj.ObjectId))
            {
                m_mapObject.Add(obj.ObjectId, obj);

                if (ObjectEnterEvent != null)
                    ObjectEnterEvent(obj);

                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// get a object in this world
    /// </summary>
    /// <param name="ObjectId"></param>
    /// <returns></returns>
    public objectinfo.LogicObject GetObject(int ObjectId)
    {
        lock (m_lockObj)
        {
            objectinfo.LogicObject obj;
            if (m_mapObject.TryGetValue(ObjectId, out obj))
                return obj;
        }

        return null;
    }

    /// <summary>
    /// get a player digest
    /// </summary>
    /// <param name="ObjectId"></param>
    /// <returns></returns>
    public objectinfo.PlayerInfoDigest GetPlayerDigest(int ObjectId)
    {
        lock (m_lockObj)
        {
            objectinfo.PlayerInfoDigest digest;
            if (m_mapPlayer.TryGetValue(ObjectId, out digest))
                return digest;
        }

        return null;
    }

    /// <summary>
    /// remove a object
    /// </summary>
    /// <param name="ObjectId"></param>
    public void Remove(int ObjectId)
    {
        lock (m_lockObj)
        {
            objectinfo.LogicObject obj;
            if (m_mapObject.TryGetValue(ObjectId, out obj))
            {
                m_mapObject.Remove(ObjectId);
                objectinfo.PlayerInfoDigest digest;
                if (m_mapPlayer.TryGetValue(ObjectId, out digest))
                {
                    m_mapPlayer.Remove(ObjectId);
                    if (PlayerLeaveEvent != null)
                        PlayerLeaveEvent(digest);
                }
                else
                {
                    if (ObjectLeaveEvent != null)
                        ObjectLeaveEvent(obj);
                }
            }
        }
    }
    #endregion
}